#include "cJSON.h"
#include "ml307.h"
#include "ml307_json_cmd.h"
#include "ml307_parm.h"
#include "ml307_thread.h"
// ml_num_count

cJSON* json_cmd_create_reply_v2(const char* cmd, const char* method, cJSON* arg) {
    cJSON* root = cJSON_CreateObject();
    cJSON_AddStringToObject(root, "cmd", cmd);
    cJSON_AddStringToObject(root, "method", method);
    cJSON_AddItemToObject(root, "arg", arg);
    return root;
}
int set_change_ml_conut(cJSON* json);

void ml_count_handler(const char* cmd, const char* method, cJSON* arg, void* user_arg,
                      char* out_str, uint16_t out_len) {
    if (out_str == NULL || out_len == 0) {
        return;
    }
    // printf("%s\n", __func__);

    cJSON* reply_node = NULL;
    cJSON* reply_root = NULL;
    // get
    if (strcmp(method, "get") == 0) {
        reply_root = cJSON_CreateObject();
        if (reply_root == NULL) {
            return;
        }
        cJSON_AddStringToObject(reply_root, "cmd", cmd);
        cJSON_AddStringToObject(reply_root, "method", method);

        reply_node = cJSON_CreateObject();
        if (reply_node == NULL) {
            cJSON_Delete(reply_root);
            return;
        }
        cJSON_AddNumberToObject(reply_node, "mqttc_num", ml307_cfg.ml307_mqttc_num);
        cJSON_AddItemToObject(reply_root, "arg", reply_node);
        // set
    } else {
        int result = -1;
        if (strcmp(method, "set") == 0) {
            result = set_change_ml_conut(arg);
        }

        reply_node = cJSON_CreateObject();
        if (result == 0) {
            cJSON_AddStringToObject(reply_node, "status", "ok");
        } else {
            cJSON_AddStringToObject(reply_node, "status", "fail");
        }
        reply_root = json_cmd_create_reply_v2(cmd, method, reply_node);
    }
    // reply_root
    if (reply_root) {
        int result = cJSON_PrintPreallocated(reply_root, (char*)out_str, out_len, 0);
        cJSON_Delete(reply_root);
    }
}

int set_change_ml_conut(cJSON* json) {
    if (json == NULL) {
        return -1;
    }
    cJSON* ml_num_count = cJSON_GetObjectItem(json, "mqttc_num");
    if (ml_num_count == NULL || !cJSON_IsNumber(ml_num_count)) {
        return -1;  // 参数无效
    }
    int count = ml_num_count->valueint;
    if (count < 1 || count > 4) {
        return -1;  // 数值范围不合法
    }
    // 更新ml307_cfg的ml_num_count
    ml307_cfg.ml307_mqttc_num = count;
    return 0;
}

// 模组mqtt的配置
cJSON* ml_mqtt_cfg_get(uint16_t start_index, uint16_t sum);
int ml_mqtt_cfg_set(cJSON* json);
void ml_mqtt_cfg_handler(const char* cmd, const char* method, cJSON* arg, void* user_arg,
                         char* out_str, uint16_t out_len) {
    if (out_str == NULL || out_len == 0) {
        return;
    }
    // printf("%s\n", __func__);

    cJSON* reply_node = NULL;
    cJSON* reply_root = NULL;
    // get
    if (strcmp(method, "get") == 0) {
        cJSON* index = cJSON_GetObjectItem(arg, "index");
        cJSON* count = cJSON_GetObjectItem(arg, "count");
        if (index && count) {
            uint16_t int_index = index->valueint;
            uint16_t int_count = count->valueint;
					  
            reply_node = ml_mqtt_cfg_get(int_index, int_count);
            reply_root = json_cmd_create_reply_v2(cmd, method, reply_node);
        }
        // set
    } else {
        int result = -1;
        if (strcmp(method, "set") == 0) {
            result = ml_mqtt_cfg_set(arg);
        }

        reply_node = cJSON_CreateObject();
        if (result == 0) {
            cJSON_AddStringToObject(reply_node, "status", "ok");
        } else {
            cJSON_AddStringToObject(reply_node, "status", "fail");
        }
        reply_root = json_cmd_create_reply_v2(cmd, method, reply_node);
    }
    // reply_root
    if (reply_root) {
        int result = cJSON_PrintPreallocated(reply_root, (char*)out_str, out_len, 0);
        cJSON_Delete(reply_root);
    }
}
cJSON* ml_mqtt_cfg_get(uint16_t index, uint16_t sum) {
    uint16_t unm = ml307_cfg.ml307_mqttc_num;
    if (index > unm) {
        return NULL;
    }
    cJSON* arg = cJSON_CreateObject();
    cJSON* config_json = cJSON_CreateArray();
    if (arg == NULL || config_json == NULL) {
        return NULL;
    }
		cJSON_AddNumberToObject(arg, "mq_index", ml307_cfg.smqtt[index].ml307_mqtt_id);
    cJSON_AddNumberToObject(arg, "mq_status", ml307_cfg.smqtt[index].mqttc_link);
    cJSON_AddNumberToObject(arg, "ssl_enable", ml307_cfg.smqtt[index].ssl);
    cJSON_AddNumberToObject(arg, "topic_mux_enable", ml307_cfg.smqtt[index].topic_mux);
    cJSON_AddStringToObject(arg, "ip_host", ml307_cfg.smqtt[index].host);
    cJSON_AddStringToObject(arg, "client_id", ml307_cfg.smqtt[index].client_id);
    cJSON_AddStringToObject(arg, "user_name", ml307_cfg.smqtt[index].user_name);
    cJSON_AddStringToObject(arg, "pass_word", ml307_cfg.smqtt[index].pass_word);
    cJSON_AddStringToObject(arg, "subtopic", ml307_cfg.smqtt[index].SubTopic[0].subtopic);
    cJSON_AddStringToObject(arg, "subtopic1", ml307_cfg.smqtt[index].SubTopic[1].subtopic);
    cJSON_AddStringToObject(arg, "subtopic2", ml307_cfg.smqtt[index].SubTopic[2].subtopic);
    cJSON_AddStringToObject(arg, "pubtopic", ml307_cfg.smqtt[index].PubTopic);
    cJSON_AddNumberToObject(arg, "port", ml307_cfg.smqtt[index].port);
    cJSON_AddNumberToObject(arg, "Qos", ml307_cfg.smqtt[index].Qos);
    cJSON_AddItemToArray(config_json,arg);
    return config_json;
}
#define SAFE_COPY1(dest, src, size)     \
    do {                                \
        strncpy(dest, src, (size) - 1); \
        dest[(size) - 1] = '\0';        \
    } while (0)
int ml_mqtt_cfg_set(cJSON* arg) {
    if (arg == NULL) {
        return -1;
    }
    cJSON* json_index = cJSON_GetObjectItemCaseSensitive(arg, "index");  // 解析index

    cJSON* ssl_enable = cJSON_GetObjectItemCaseSensitive(arg, "ssl_enable");
    cJSON* topic_mux = cJSON_GetObjectItemCaseSensitive(arg, "topic_mux_enable");
    cJSON* ip_host = cJSON_GetObjectItemCaseSensitive(arg, "ip_host");
    cJSON* port = cJSON_GetObjectItemCaseSensitive(arg, "port");
    cJSON* client_id = cJSON_GetObjectItemCaseSensitive(arg, "client_id");  // 修正拼写
    cJSON* user_name = cJSON_GetObjectItemCaseSensitive(arg, "user_name");
    cJSON* pass_word = cJSON_GetObjectItemCaseSensitive(arg, "pass_word");
    cJSON* subtopic = cJSON_GetObjectItemCaseSensitive(arg, "subtopic");
    cJSON* subtopic1 = cJSON_GetObjectItemCaseSensitive(arg, "subtopic1");
    cJSON* subtopic2 = cJSON_GetObjectItemCaseSensitive(arg, "subtopic2");
    cJSON* pubtopic = cJSON_GetObjectItemCaseSensitive(arg, "pubtopic");
    cJSON* qos = cJSON_GetObjectItemCaseSensitive(arg, "Qos");
    uint16_t index = json_index->valueint;
    if (ssl_enable && cJSON_IsNumber(ssl_enable)) {
        ml307_cfg.smqtt[index].ssl = ssl_enable->valueint ? 1 : 0;
    }
    if (topic_mux && cJSON_IsNumber(topic_mux)) {
        ml307_cfg.smqtt[index].topic_mux = topic_mux->valueint ? 1 : 0;
    }
    if (ip_host && cJSON_IsString(ip_host)) {
        SAFE_COPY1(ml307_cfg.smqtt[index].host, ip_host->valuestring,
                   sizeof(ml307_cfg.smqtt[index].host));
    }
    if (port && cJSON_IsNumber(port)) {
        ml307_cfg.smqtt[index].port = port->valueint;
    }
    if (client_id && cJSON_IsString(client_id)) {
        SAFE_COPY1(ml307_cfg.smqtt[index].client_id, client_id->valuestring,
                   sizeof(ml307_cfg.smqtt[index].client_id));
    }
    if (user_name && cJSON_IsString(user_name)) {
        SAFE_COPY1(ml307_cfg.smqtt[index].user_name, user_name->valuestring,
                   sizeof(ml307_cfg.smqtt[index].user_name));
    }
    if (pass_word && cJSON_IsString(pass_word)) {
        SAFE_COPY1(ml307_cfg.smqtt[index].pass_word, pass_word->valuestring,
                   sizeof(ml307_cfg.smqtt[index].pass_word));
    }
    if (subtopic && cJSON_IsString(subtopic)) {
        SAFE_COPY1(ml307_cfg.smqtt[index].SubTopic[0].subtopic, subtopic->valuestring,
                   sizeof(ml307_cfg.smqtt[index].SubTopic[0].subtopic));
    }
    if (subtopic1 && cJSON_IsString(subtopic1)) {
        SAFE_COPY1(ml307_cfg.smqtt[index].SubTopic[1].subtopic, subtopic1->valuestring,
                   sizeof(ml307_cfg.smqtt[index].SubTopic[1].subtopic));
    }
    if (subtopic2 && cJSON_IsString(subtopic2)) {
        SAFE_COPY1(ml307_cfg.smqtt[index].SubTopic[2].subtopic, subtopic2->valuestring,
                   sizeof(ml307_cfg.smqtt[index].SubTopic[2].subtopic));
    }
    if (pubtopic && cJSON_IsString(pubtopic)) {
        SAFE_COPY1(ml307_cfg.smqtt[index].PubTopic, pubtopic->valuestring,
                   sizeof(ml307_cfg.smqtt[index].PubTopic));
    }
    if (qos && cJSON_IsNumber(qos)) {
        ml307_cfg.smqtt[index].Qos = (qos->valueint > 2) ? 0 : qos->valueint;
    }
		j_parm_set_parm_update_flag(j_parm, "ml_cfg");
    return 0;
}
/// 获取4G信号
cJSON* ml_slm_status_get(void);
void ml_4g_status_handler(const char* cmd, const char* method, cJSON* arg, void* user_arg,
                          char* out_str, uint16_t out_len) {
    if (out_str == NULL || out_len == 0) {
        return;
    }
    // printf("%s\n", __func__);

    cJSON* reply_node = NULL;
    cJSON* reply_root = NULL;
    // get
    if (strcmp(method, "get") == 0) {
        reply_node = ml_slm_status_get();
        reply_root = json_cmd_create_reply_v2(cmd, method, reply_node);

        // set
    } else {
    }
    // reply_root
    if (reply_root) {
        int result = cJSON_PrintPreallocated(reply_root, (char*)out_str, out_len, 0);
        cJSON_Delete(reply_root);
    }
}
cJSON* ml_slm_status_get(void) {
    cJSON* root = cJSON_CreateObject();
    if (root == NULL) {
        return NULL;
    }
    cJSON* arg = cJSON_CreateObject();
    if (arg == NULL) {
        cJSON_Delete(root);
        return NULL;
    }
    cJSON_AddItemToObject(root, "arg", arg);
    cJSON_AddNumberToObject(arg, "ml_online",
                            ml307_cfg.ml307_status);  // 1:online, 2:power_on, 3:power_down
    cJSON_AddStringToObject(arg, "imsi", ml307_cfg.ml307_net_info_t.imsi);
    cJSON_AddStringToObject(arg, "reg_ip", ml307_cfg.ml307_net_info_t.ip_4g);
    cJSON_AddStringToObject(arg, "iccid", ml307_cfg.ml307_net_info_t.iccid);
    cJSON_AddStringToObject(arg, "operator", ml307_cfg.ml307_net_info_t.net_name);
    cJSON_AddNumberToObject(arg, "rssi", ml307_cfg.ml307_net_info_t.db_singal);
    return root;
}
////自动注册
int set_reg_ml(cJSON* json);
void ml_reg_handler(const char* cmd, const char* method, cJSON* arg, void* user_arg, char* out_str,
                    uint16_t out_len) {
    if (out_str == NULL || out_len == 0) {
        return;
    }
    // printf("%s\n", __func__);

    cJSON* reply_node = NULL;
    cJSON* reply_root = NULL;
    // get
    if (strcmp(method, "get") == 0) {
        reply_root = cJSON_CreateObject();
        if (reply_root == NULL) {
            return;
        }
        cJSON_AddStringToObject(reply_root, "cmd", cmd);
        cJSON_AddStringToObject(reply_root, "method", method);

        reply_node = cJSON_CreateObject();
        if (reply_node == NULL) {
            cJSON_Delete(reply_root);
            return;
        }
        cJSON_AddNumberToObject(reply_node, "ato_reg_en", get_http_register_enable());
        cJSON_AddNumberToObject(reply_node, "reg_sta", get_http_register_status());
        cJSON_AddNumberToObject(reply_node, "sp_time", get_sptime());  // 转换为秒
        cJSON_AddNumberToObject(reply_node, "productId", 164);
        cJSON_AddStringToObject(reply_node, "deviceName", "test");
        cJSON_AddStringToObject(reply_node, "userKey","test_key");
        
        cJSON_AddItemToObject(reply_root, "arg", reply_node);
        // set
    } else {
        int result = -1;
        if (strcmp(method, "set") == 0) {
            result = set_reg_ml(arg);
        }

        reply_node = cJSON_CreateObject();
        if (result == 0) {
            cJSON_AddStringToObject(reply_node, "status", "ok");
        } else {
            cJSON_AddStringToObject(reply_node, "status", "fail");
        }
        reply_root = json_cmd_create_reply_v2(cmd, method, reply_node);
    }
    // reply_root
    if (reply_root) {
        int result = cJSON_PrintPreallocated(reply_root, (char*)out_str, out_len, 0);
        cJSON_Delete(reply_root);
    }
}
int set_reg_ml(cJSON* json) {
    if (json == NULL) {
        return -1;
    }
    cJSON* enable = cJSON_GetObjectItem(json, "enable");
    cJSON* sp_time = cJSON_GetObjectItem(json, "sp_time");
    cJSON* productId = cJSON_GetObjectItem(json, "productId");
    cJSON* deviceName = cJSON_GetObjectItem(json, "deviceName");
    cJSON* userKey = cJSON_GetObjectItem(json, "userKey");
    // 更新ml307_cfg
    set_http_register_enable(enable->valueint);
    if (sp_time->valueint < 0 || sp_time->valueint > 3600) {
        return -1;
    }
    uint16_t sp_time_value = (uint16_t)sp_time->valueint * (1000);
    set_sptime(sp_time_value);
		j_parm_set_parm_update_flag(j_parm, "ml_cfg");
    return 0;
}

void ml_mqtt_sta_handler(const char* cmd, const char* method, cJSON* arg, void* user_arg,
                         char* out_str, uint16_t out_len) {
    if (out_str == NULL || out_len == 0) {
        return;
    }
    // printf("%s\n", __func__);

    cJSON* reply_node = NULL;
    cJSON* reply_root = NULL;
    // get
    if (strcmp(method, "get") == 0) {
        reply_root = cJSON_CreateObject();
        if (reply_root == NULL) {
            return;
        }
        cJSON_AddStringToObject(reply_root, "cmd", cmd);
        cJSON_AddStringToObject(reply_root, "method", method);

        reply_node = cJSON_CreateObject();
        if (reply_node == NULL) {
            cJSON_Delete(reply_root);
            return;
        }
        cJSON_AddNumberToObject(reply_node, "mq_sta0", get_ml307_mqttc_link(0));
        //cJSON_AddNumberToObject(reply_node, "mq_sta1", get_http_register_status());
        //cJSON_AddNumberToObject(reply_node, "mq_sta2", get_http_register_enable());
        cJSON_AddItemToObject(reply_root, "arg", reply_node);
        // set
    } else {
    }
    // reply_root
    if (reply_root) {
        int result = cJSON_PrintPreallocated(reply_root, (char*)out_str, out_len, 0);
        cJSON_Delete(reply_root);
    }
}
